import sys
import binascii
import struct
sys.path.append(sys.path[0] + "/../interpreter")
from llvm import *



#API
# checkType(variable, desired type, good label, bad label)
# signalError(error number)
# createFloat([intial value], [temp], [shift])
# loadObjType(pointer)
class commonRoutines:
	def __init__(self, helper):
		self.helper = helper
		
	def checkType(self, variable, typeValue, goodlabel, badlabel = None):
		typeTable = {'int':0, 'bool':3, 'null':2, 'pointer':1, 'plain object': 0, 'float': 3, 'string': 2, 'closure': 1, 'temp float': 7}
		
		if(type(typeValue) == type("")): #string const, convert
			typeVal = typeTable[typeValue]
		else:
			typeVal = typeValue
		
		maskReg = self.helper.getNextReg()
		branchReg = self.helper.getNextReg()
		
		self.helper.addLLVMLine("; Check Type:")
		
		if(typeVal < 4 ):
			self.helper.addLLVMInst(llvm_and(maskReg, variable, "3"), "Masking off bottom 2 bits")
		else:
			self.helper.addLLVMInst(llvm_and(maskReg, variable, "7"), "Masking off bottom 3 bits")
			
		self.helper.addLLVMInst(llvm_icmp_eq(branchReg, maskReg, str(typeVal)), "comparing on bottom 2/3 bits matching: " + str(typeValue))
		if (badlabel != None):
			self.helper.addLLVMInst(llvm_brc(branchReg, goodlabel, badlabel), "Branch!")
		else:
			tempLabel = self.helper.getNextLabel()
			self.helper.addLLVMInst(llvm_brc(branchReg, tempLabel, goodlabel), "Make sure this isn't the case")
			self.helper.addLLVMLabel(tempLabel, "fall through bevarior")
	
	def signalError(self, errorNum):
#		self.helper.addLLVMLine( "call void @printerror(i32 " + str(errorNum)+ ") noreturn")#error
		self.helper.addLLVMInst(llvm_call("printerror", "void", None, errorNum), "Error!")
		self.helper.addLLVMLine( "unreachable")
	
	def fetchVar(self, numberOfEframes, index):
		result =  self.helper.getNextReg()
		self.helper.addLLVMInst(llvm_call("getVarFromScope", "i32", result, self.helper.getCurrentScopeReg(), "i32", numberOfEframes, "i32", index, "i32"))
		return result


	def fetchSlotsVar(self, slotsReg, memberNum):
		result =  self.helper.getNextReg()
		emptySlotsAsInt = self.helper.getNextReg()
		
		self.helper.addLLVMInst(llvm_ptrtoint(emptySlotsAsInt, "@empty_slots", "%slots*", "i32"), "Turn slots into an i32")
		self.helper.addLLVMInst(llvm_call("getVarFromSlots", "i32", result, slotsReg, "i32", memberNum, "i32", emptySlotsAsInt))
		return result
		
	def setVar(self, numberOfEframes, index, value, inlineScope = None):
		if(inlineScope == None):
			self.helper.addLLVMInst(llvm_call("storeVarInScope", "i32", None, self.helper.getCurrentScopeReg(), "i32", numberOfEframes, "i32", index, "i32", value, "i32"))
		else:
			self.helper.addLLVMInst(llvm_call("storeVarInScope", "i32", None, inlineScope, "i32", numberOfEframes, "i32", index, "i32", value, "i32"))
		
	def mutateSlotsVar(self, slotsReg, memberNum, value):
		result =  self.helper.getNextReg()
		emptySlotsAsInt = self.helper.getNextReg()
		
		self.helper.addLLVMInst(llvm_ptrtoint(emptySlotsAsInt, "@empty_slots", "%slots*", "i32"), "Turn slots into an i32")
		self.helper.addLLVMInst(llvm_call("mutateSlotsVar", "i32", result, slotsReg, "i32", memberNum, "i32", value, "i32", emptySlotsAsInt))
		return result
	
# CREATE functions
	def createEframe(self, size, firstInFunction = False, firstEver = False):
		mallocReg = self.helper.getNextReg()
		bitcastReg = self.helper.getNextReg()
		scopeLastScope = self.helper.getNextReg()
		scopeVarCountAddr = self.helper.getNextReg()
		secondBitcastReg = self.helper.getNextReg()
		pointerAsIntReg = self.helper.getNextReg()
		taggedInt = self.helper.getNextReg()
		
		if(firstInFunction):
			size += len(self.helper.getCurrentFunctionArgs())
		
		self.helper.addLLVMLine("; Create EFrame:")

		scopeReg =  self.helper.getCurrentScopeReg()

		self.helper.addLLVMInst(llvm_malloc(mallocReg, "{%eframe*, i32, [" + str(size) + " x i32 ]}"), "Creating eframe")
		self.helper.addLLVMInst(llvm_bitcast(bitcastReg, mallocReg, "{%eframe*, i32, [" + str(size) + " x i32 ]}*", "%eframe*"), "Bitcasting to eframe*")
		self.helper.addLLVMInst(llvm_gep(scopeLastScope, bitcastReg, "%eframe*", 0, "i32", 0), "getting pointer to previous")
		if(firstEver):
			self.helper.addLLVMInst(llvm_store(scopeReg, scopeLastScope, "%eframe*", "%eframe*"), "saving previous scope")
		elif(firstInFunction):
			self.helper.addLLVMInst(llvm_store("%env", scopeLastScope, "%eframe*", "%eframe*"), "saving previous scope")
		else:
			unmakedEframe =  self.testAndUnmaskPointer(scopeReg, "%eframe*")
			self.helper.addLLVMInst(llvm_store(unmakedEframe, scopeLastScope, "%eframe*", "%eframe*"), "saving previous scope - IN BASIC BLOCK")
		self.helper.addLLVMInst(llvm_gep(scopeVarCountAddr, bitcastReg, "%eframe*", 0, "i32", 1), "getting pointer to var count")
		self.helper.addLLVMInst(llvm_store(str(size), scopeVarCountAddr, "i32", "i32"), "saving count")
		self.helper.addLLVMInst(llvm_bitcast(secondBitcastReg, bitcastReg, "%eframe*", "i32*"), "Bitcasting to i32*")
		self.helper.addLLVMInst(llvm_ptrtoint(pointerAsIntReg, secondBitcastReg, "i32*", "i32"), "turning pointer into int")		
		self.helper.addLLVMInst(llvm_add(taggedInt, pointerAsIntReg, "1"), "adding tag")
		
		if(firstInFunction):
			args = self.helper.getCurrentFunctionArgs()
			for i in range(len(args)):
				self.setVar(0,i,args[i][1],taggedInt)
		
		return taggedInt

	def ieee754(self, val):
  		return hex(struct.unpack('<Q', struct.pack('d', val))[0])[0:18]
		
	def createFloat(self, initialValue = None, temp = False, shift = False, new = False):
		#sys.stderr.write("INIT FLOAT VAL: " + str(initialValue) + "\n")
		pointerReg = self.helper.getNextReg()
		pointerAsIntReg = self.helper.getNextReg()
		tagAddrReg = self.helper.getNextReg()
		floatAddrReg = self.helper.getNextReg() 
		#sys.stderr.write("FLOAT VAL: " + initialValue + "\n")
		self.helper.addLLVMLine("; Create Float:")
		
#	 	self.helper.addLLVMLine(str(pointerReg) + " = malloc %floatobj, align 4", "Create Float")
		self.helper.addLLVMInst(llvm_malloc(pointerReg, "%floatobj"), "Create Float")
	 	pointerAsIntReg = self.pointerToInt(pointerReg, "%floatobj")
		
		if(temp): # absense of a type argument means it'll be i32
			self.setObjType(pointerAsIntReg, 7)
		else:
			self.setObjType(pointerAsIntReg, 3)
		
		
		if(initialValue == None):
			self.storeFloatValue(pointerAsIntReg, float(0))
		else:
			if(type(initialValue) != type("")):
	#			storeFloatValue(self.helper, pointerAsIntReg, "0x"+binascii.hexlify(str(float(initialValue))))
				#try this
				#self.storeFloatValue(pointerAsIntReg, "0x3FF0000000000000")
				val = self.ieee754(initialValue)
				sys.stderr.write("FLOAT VAL: " + str(val) + " in " + pointerAsIntReg +"\n")
				#sys.stderr.write("hex VAL: " + str(self.helper.toHex("A")) + "\n")
				#sys.stderr.write("FLOAT VAL with to hex: " + str(val2) + "\n")
				self.storeFloatValue(pointerAsIntReg, val, True)
			else:
				if(shift):
					shiftedRegValue = self.helper.getNextReg()
					intAsFloat = self.helper.getNextReg()
					
					self.helper.addLLVMInst(llvm_lshr(shiftedRegValue, initialValue, "2"), "Shifting Int to avoid tag")
			#		self.helper.addLLVMInst(llvm_and(shiftedRegValue, initialValue, int('0xFFFFFFFC',16)), "Anding to remove tag")
					self.helper.addLLVMInst(llvm_uitofp(intAsFloat, shiftedRegValue, "i32", "float"), "untagged int -> Float")
					self.storeFloatValue(pointerAsIntReg, intAsFloat)
				else:
					self.storeFloatValue(pointerAsIntReg, initialValue)
			
		return pointerAsIntReg
		
	def loadObjType(self, pointer, objType = "%floatobj*"):
		typeReg = self.helper.getNextReg()
		objTypeVal = self.helper.getNextReg()
		
		self.helper.addLLVMLine("; Load Object Type:")
		
		#self.helper.addLLVMLine(str(typeReg) + " = getelementptr %floatobj* " + str(self.testAndUnmaskPointer(pointer)) + ", i32 0, i32 0", "Load Object Type")
		self.helper.addLLVMInst(llvm_gep(typeReg, self.testAndUnmaskPointer(pointer, objType), objType, 0, "i32", 0), "Load " + objType + " Type")
		self.helper.addLLVMInst(llvm_load(objTypeVal, typeReg), "Load type value register.")
		return objTypeVal
		
	def loadClosureValue(self, pointer):
		typeReg = self.helper.getNextReg()
		closureValReg = self.helper.getNextReg()
		
		self.helper.addLLVMLine("; Load Closure Value:")
		
		#self.helper.addLLVMLine(str(typeReg) + " = getelementptr %floatobj* " + str(self.testAndUnmaskPointer(pointer)) + ", i32 0, i32 0", "Load Object Type")
		self.helper.addLLVMInst(llvm_gep(typeReg, self.testAndUnmaskPointer(pointer, "%closure*"), "%closure*", 0, "i32", 1), "Load Closure Number")
		self.helper.addLLVMInst(llvm_load(closureValReg, typeReg), "Load type Closure Number.")
		return closureValReg
		
	def setObjType(self, pointer, typeVal, objType = "%floatobj*"):
		typePtr = self.helper.getNextReg()
		
		self.helper.addLLVMLine("; Set Object Type:")
		
		ptr = self.testAndUnmaskPointer(pointer, objType)
		#self.helper.addLLVMLine(str(typePtr) + " = getelementptr %floatobj* " + str(ptr) + ", i32 0, i32 0", "Load Object Type to Set")
		self.helper.addLLVMInst(llvm_gep(typePtr, ptr, objType, 0, "i32", 0), "Load Object Type to Set")
		self.helper.addLLVMInst(llvm_store(typeVal,typePtr), "Store passed value to propper address")
		
	def testAndUnmaskPointer(self, pointer, typ = "%floatobj*", errorLabel = False):
		pointerLabel = self.helper.getNextLabel()
		typeReg = self.helper.getNextReg()
		unMaskedIntReg = self.helper.getNextReg()
		unMaskedPointerReg = self.helper.getNextReg()
		
		if(errorLabel):
			errorLabel = self.helper.getNextLabel()
			self.checkType(pointer, "pointer", pointerLabel, errorLabel)
			self.helper.addLLVMLabel(errorLabel, "Error label: Pointer")
			self.signalError(30)
			self.helper.addLLVMLabel(pointerLabel, "Value passes as Pointer")
			
		
		self.helper.addLLVMInst(llvm_and(unMaskedIntReg, pointer, int('0xFFFFFFFC',16), "i32"), "Un-masking pointer")
		self.helper.addLLVMInst(llvm_inttoptr(unMaskedPointerReg, unMaskedIntReg, "i32", str(typ)))
		return unMaskedPointerReg
			
	def pointerToInt(self, pointer, typ):
		ptrAsIntReg = self.helper.getNextReg()
		taggedPtrReg = self.helper.getNextReg()
		
		self.helper.addLLVMLine("; Pointer To Int:")
		
		self.helper.addLLVMInst(llvm_ptrtoint(ptrAsIntReg, pointer, str(typ)+"*", "i32"), "Changing pointer into Int")
		self.helper.addLLVMInst(llvm_add(taggedPtrReg, ptrAsIntReg, "1"), "Adding Tag")
		
		return taggedPtrReg
			
	def loadFloatValue(self, pointer):
		floatPtr = self.helper.getNextReg()
		floatVal = self.helper.getNextReg()
		
		self.helper.addLLVMLine("; Load Float Value:")
		
		unMaskedPointerReg = self.testAndUnmaskPointer(pointer)
		
		self.helper.addLLVMInst(llvm_gep(floatPtr, unMaskedPointerReg, "%floatobj*", 0, "i32", 1), "Loading pointer to value of Float")
		#self.helper.addLLVMLine(str(floatPtr) + " = getelementptr %floatobj* " + str(unMaskedPointerReg) + ", i32 0, i32 1", "Loading pointer to value of Float")
		self.helper.addLLVMInst(llvm_load(floatVal, floatPtr, "float"), "Loading actual value")
		return floatVal
		
	def storeFloatValue(self, pointer, value, new = False):
		floatPtr = self.helper.getNextReg()
		truncFloat = self.helper.getNextReg()
		self.helper.addLLVMLine("; Store Float Value:")
		
		unMaskedPointerReg = self.testAndUnmaskPointer(pointer)
	#	temp1 = self.helper.getNextReg()
	#	temp2 = self.helper.getNextReg()
	#	temp3 = self.helper.getNextReg()
		
		self.helper.addLLVMInst(llvm_gep(floatPtr, unMaskedPointerReg, "%floatobj*", 0, "i32", 1), "Loading Address for float")
		#self.helper.addLLVMLine(str(floatPtr) + " = getelementptr %floatobj* " + str(unMaskedPointerReg) + ", i32 0, i32 1", "Loading address for float")
		
	#	self.helper.addLLVMLine(str(temp1) + " = bitcast float* " + str(floatPtr) + " to i32*")
	#	self.helper.addLLVMInst(llvm_ptrtoint(temp2, temp1, "i32*", "i32"))
	#	self.helper.debugPrint(temp2, "a")
	#	self.helper.debugPrintFloatPtr(floatPtr)
		
		if(type(value) == type(0)):
			self.helper.addLLVMInst(llvm_store(binascii.hexlify(float(value)), floatPtr, "float", "float"), "Adding value with literal")
		else:
	#		self.helper.debugPrintFloat(value)
			if(new):
				self.helper.addLLVMInst(llvm_fptrunc(truncFloat, value, "double", "float"),"FLP GETTING CRUNK!")
				self.helper.addLLVMInst(llvm_store(truncFloat, floatPtr, "float", "float"), "Adding value with register!")
			else:
				self.helper.addLLVMInst(llvm_store(value, floatPtr, "float", "float"), "Adding value with register!")
	#		self.helper.addLLVMInst(llvm_load(temp3, floatPtr, "float"), "Loading for print!")
	#		self.helper.debugPrintFloat(temp3)
			
	
	def floatIntBinaryOp(self, leftSide, rightSide, IntInst, FloatInst, branch = False, errorNumber = 0):
			#Labels
			firstNumi32 = self.helper.getNextLabel()
			floatTest0 = self.helper.getNextLabel()
			floatTest1 = self.helper.getNextLabel()
			
			float1Temp = self.helper.getNextLabel()
			float2Temp = self.helper.getNextLabel()
			createNewFloat = self.helper.getNextLabel()
			
			setFloatStorageAddr = self.helper.getNextLabel()
			
			Int2WithFloat1 = self.helper.getNextLabel()
			Int2ToFloat2 = self.helper.getNextLabel()
			Int1WithFloat2 = self.helper.getNextLabel()
			Int1ToFloat1 = self.helper.getNextLabel()
			
			typeErrorLabel = self.helper.getNextLabel()
			
			floatOp = self.helper.getNextLabel()
			intOp = self.helper.getNextLabel()
			endLabel = self.helper.getNextLabel()
			#Registers
			previousFloatAddr = self.helper.getNextReg()
			nonTempFloatAddr = self.helper.getNextReg()
			floatResultAddrReg = self.helper.getNextReg()
			
			floatValueForNewTemp = self.helper.getNextReg()
			
			floatOpAddr1 = self.helper.getNextReg()
			floatOpAddr2 = self.helper.getNextReg()
			tempFloatValue = self.helper.getNextReg()
			intOpReg1 = self.helper.getNextReg()
			intOpReg2 = self.helper.getNextReg()
			preShiftReg = self.helper.getNextReg()
			intResult = self.helper.getNextReg()
			targetReg = self.helper.getNextReg()
	
#			self.helper.debugPrint(0)
			self.helper.debugPrint(leftSide, "a")
			self.helper.debugPrint(rightSide, "b")
			self.checkType(leftSide, "int", firstNumi32, floatTest0)
			
			#first num is float
			self.helper.addLLVMLabel(floatTest0, "Checking if leftSide is float")
#			self.helper.debugPrint(1)
			self.checkType(leftSide, "pointer", typeErrorLabel)
			PointerOneType = self.loadObjType(leftSide)
			self.checkType(PointerOneType, "float", floatTest1, typeErrorLabel)
			
			self.helper.addLLVMLabel(floatTest1, "Checking if rightSide is float")
#			self.helper.debugPrint(2)
			self.checkType(rightSide, "pointer", Int2WithFloat1)
			PointerTwoType = self.loadObjType(rightSide)
			self.checkType(PointerTwoType, "float", float1Temp, Int2WithFloat1)
	
			# ---------------------------------------
			# finding temp float		
			self.helper.addLLVMLabel(float1Temp, "Checking if float1 is a temp")
#			self.helper.debugPrint(3)
			self.checkType(PointerOneType, "temp float", setFloatStorageAddr, float2Temp) # storage place = argVal[0]
			float1IsTempLabel =  self.helper.getLastLabel()
			
			self.helper.addLLVMLabel(float2Temp, "Checking if float2 is a temp")
#			self.helper.debugPrint(4)
			self.checkType(PointerTwoType, "temp float", setFloatStorageAddr, createNewFloat) # storage place = argVal[1]
			float2IsTempLabel = self.helper.getLastLabel()
			
			self.helper.addLLVMLabel(createNewFloat, "Creating new Float")
#			self.helper.debugPrint(5)
			floatValueForNewTemp = self.loadFloatValue(leftSide) # put argValue[0]'s value into the new float, use AV[1] for other op
			newFloatReg = self.createFloat(floatValueForNewTemp,True)

			self.helper.addLLVMInst(llvm_br(floatOp), "Branching to floatOp with new float")
			NewTempFloatLabel = self.helper.getLastLabel()
	
	
			self.helper.addLLVMLabel(setFloatStorageAddr, "Selecting float addrs based on which float was temp")
			self.helper.addLLVMLine(str(previousFloatAddr) + " = phi i32 [ "+ str(leftSide) +", %"+str(float1IsTempLabel)+" ], [ "+str(rightSide)+", %"+str(float2IsTempLabel)+" ]")
			self.helper.addLLVMLine(str(nonTempFloatAddr) + " = phi i32 [ "+ str(rightSide) +", %"+str(float2IsTempLabel)+" ], [ "+str(leftSide)+", %"+str(float1IsTempLabel)+" ]")
#			self.helper.debugPrint(6)
			self.helper.addLLVMInst(llvm_br(floatOp), "Branching to FloatOp with two previous floats")
			existingFloatIsTempLabel = self.helper.getLastLabel()
			# ---------------------------------------
			# end finding temp float
			
			self.helper.addLLVMLabel(Int2WithFloat1)
#			self.helper.debugPrint(7)
			self.checkType(rightSide, "int", Int2ToFloat2, typeErrorLabel)
			
			self.helper.addLLVMLabel(Int2ToFloat2, "Change 2nd int to a float")
#			self.helper.debugPrint(8)
			floatReg1 = self.createFloat(rightSide, True, True)
			
	
			self.helper.addLLVMInst(llvm_br(floatOp), "Branching to FloatOp with 2nd int as a Float")
			The2ndIntIsFloatLabel = self.helper.getLastLabel()
			
			#first num is int		
			self.helper.addLLVMLabel(firstNumi32)
#			self.helper.debugPrint(9)
			self.checkType(rightSide, "int", intOp, Int1WithFloat2)
			
			self.helper.addLLVMLabel(Int1WithFloat2)
#			self.helper.debugPrint(10)
			self.checkType(rightSide, "pointer", typeErrorLabel)
			PointerTwoType = self.loadObjType(rightSide)
			self.checkType(PointerTwoType, "float", Int1ToFloat1, typeErrorLabel)
			
			self.helper.addLLVMLabel(Int1ToFloat1, "Change 1st inst to a float")
#			self.helper.debugPrint(11)
			floatReg0 = self.createFloat(leftSide, True, True)
			
			self.helper.addLLVMInst(llvm_br(floatOp), "Branching to FloatOp with 1st int as a Float")
			The1stIntIsFloatLabel = self.helper.getLastLabel()
			
			self.helper.addLLVMLabel(floatOp, "Float Op!")
			self.helper.addLLVMLine(str(floatOpAddr1) + " = phi i32 [ "+ str(previousFloatAddr) +", %"+str(existingFloatIsTempLabel)+" ], [ " 
						+str(newFloatReg)+", %"+str(NewTempFloatLabel)+" ], [ "
						+ str(floatReg1) +", %"+str(The2ndIntIsFloatLabel)+" ], [ "
						+ str(floatReg0) +", %"+str(The1stIntIsFloatLabel)+" ]")
			self.helper.addLLVMLine(str(floatOpAddr2) + " = phi i32 [ "+ str(nonTempFloatAddr) +", %"+str(existingFloatIsTempLabel)+" ], [ " 
						+str(rightSide)+", %"+str(NewTempFloatLabel)+" ], [ "
						+ str(leftSide) +", %"+str(The2ndIntIsFloatLabel)+" ], [ "
						+ str(rightSide) +", %"+str(The1stIntIsFloatLabel)+" ]")
			floatValue1 = self.loadFloatValue(floatOpAddr1)
			floatValue2 = self.loadFloatValue(floatOpAddr2)
			#OOOOOOP
			#
			#
			FloatInst.setTarget(tempFloatValue)
			FloatInst.setSource(0, floatValue1)
			FloatInst.setSource(1, floatValue2)
			self.helper.addLLVMInst(FloatInst, "FLOAT OP")
			if(not branch):
				self.storeFloatValue(floatOpAddr1, tempFloatValue)
				
			self.helper.addLLVMInst(llvm_br(endLabel))
			floatOpLabel = self.helper.getLastLabel()
	
			#choose values
			
	
			self.helper.addLLVMLabel(typeErrorLabel)
#			self.helper.debugPrint(13)
			self.signalError(errorNumber)
		
			self.helper.addLLVMLabel(intOp, "INT Op!")
#			self.helper.debugPrint(15)
			#OOOOOOP
			#
			#
			self.helper.addLLVMInst(llvm_lshr(intOpReg1, leftSide, "2"))
			self.helper.addLLVMInst(llvm_lshr(intOpReg2, rightSide, "2"))
			IntInst.setTarget(preShiftReg)
			IntInst.setSource(0, intOpReg1)
			IntInst.setSource(1, intOpReg2)
			self.helper.addLLVMInst(IntInst)
			if (not branch):
				self.helper.addLLVMInst(llvm_shl(intResult, preShiftReg, "2"))
			
			self.helper.addLLVMInst(llvm_br(endLabel))
			intOpLabel = self.helper.getLastLabel()
	
			self.helper.addLLVMLabel(endLabel, "End Label")
			if(branch):
				extendedReg = self.helper.getNextReg()
				unShiftedReg = self.helper.getNextReg()
				shiftedBranchReg = self.helper.getNextReg()
				self.helper.addLLVMLine(str(unShiftedReg) + " = phi i1 [ "+ str(tempFloatValue) +", %"+str(floatOpLabel)+" ], [ " 
						+str(preShiftReg)+", %"+str(intOpLabel)+" ]")
				self.helper.addLLVMInst(llvm_zext(extendedReg, unShiftedReg, "i1"), "Extending sign")
				self.helper.addLLVMInst(llvm_shl(shiftedBranchReg, extendedReg, "2"), "Shifting to add tag")
				self.helper.addLLVMInst(llvm_add(targetReg, shiftedBranchReg, "3"), "adding tag")

			else:
				self.helper.addLLVMLine(str(targetReg) + " = phi i32 [ "+ str(floatOpAddr1) +", %"+str(floatOpLabel)+" ], [ " 
						+str(intResult)+", %"+str(intOpLabel)+" ]")
						
			self.helper.debugPrint(targetReg, "c")
			return endLabel,targetReg
		
